<!DOCTYPE HTML>
<html lang="en-US">
<head>
    <meta charset="UTF-8">
    <title></title>
</head>
<body>
<button id="test">TestButton</button>
<button id="testFix">TestButton-Fix</button>
<script type="text/javascript">
    /**
     * 这个问题如果要解决，需要在与个element上记录一些数组，
     * 类似用到cache的功能：
     * //伪代码：
     * var el.fns=[];
     * fns.push(fn1);
     *
     * 但是这个并不是个好的解决方案，通常这个bind只是作为工具方法
     * 不需要这样去考虑
     * @type {*}
     */
    var testNode = document.getElementById('test');
    var testNodeFix = document.getElementById('testFix');
    window.attachEvent('onload', function () {
        console.log('window onload!');
    });
    testNode.attachEvent('onclick', function () {
        console.log('click fn1!');
    });
    testNode.attachEvent('onclick', function () {
        console.log('click fn2!');
    });
    testNode.attachEvent('onclick', function () {
        console.log('click fn3!');
    });
    /**
     * Fix这个问题得先这样思考：
     * el.handler={
     *     'click':[fn1,fn2,fn3],
     *     'mousemove':[fn1,fn2]
     *     ...
     *     ..
     * };
     *
     * @param el
     * @param eventName
     * @param fn
     */
    var hasAttach = false;
    function attach(el, eventName, fn) {
        var handler = el.handler || {};
        if (!handler[eventName]) {
            handler[eventName] = [];
        }
        handler[eventName].push(fn);
        el.handler = handler;
        if (!hasAttach) {
            el.attachEvent(eventName, function () {
                var i = 0, len = handler[eventName].length;
                console.log(len);
                for (; i < len; i++) {
                    handler[eventName][i]();
                }
            });
            hasAttach = true;
        }
    }
    /**
     * Fixed part
     */
    attach(testNodeFix, 'onclick', function () {
        console.log(1111);
    });
    attach(testNodeFix, 'onclick', function () {
        console.log(2222);
    });
    attach(testNodeFix, 'onclick', function () {
        console.log(3333);
    });
    /**
     * 总结一下：V1
     * 这个方法虽然可以解决问题，但是有几个地方不太好：
     * 1.在el上存大量的数据，这里可以通过cache方法改进
     * 大量数据会导致很多的问题：如a.ie67的内存无法释放 b.cloneNode可能会出现的潜在问题 c.深复制，继承等等
     * 2.全局对象。看以下的改进版本
     *  解决方案示意：
     *  globalCache={
     *      0:{
     *          'click':[fn1,fn2],
     *          'mouseover':[fn3,fn4]
     *      },
     *      ...
     *      5:{
     *          ...
     *      }
 *          ..
     *  };
     *
     *  el1.__EventHandlers=0;
     *  el2.__EventHandlers=5;
     */

    (function (document, window) {
        var globalCache = {},
                uid = 0,
                hasAttach = false;
        var ln = {
            attach:(function () {
                if (document.addEventListener) {
                    return function (el, eventName, fn, useCapture) {
                        el.addEventListener(eventName, fn, useCapture || false);
                    };
                } else {
                    return function (el, eventName, fn, useCapture) {
                        var handlersId = el['__EventHandlers'] = el['__EventHandlers'] || uid++;
                        var handler = globalCache[handlersId];
                        if (!handler[eventName]) {
                            handler[eventName] = [];
                        }
                        handler[eventName].push(fn);
                        globalCache[handlersId] = handler;
                        if (!hasAttach) {
                            el.attachEvent(eventName, function () {
                                var i = 0, len = handler[eventName].length;
                                for (; i < len; i++) {
                                    handler[eventName][i]();
                                }
                            });
                            hasAttach = true;
                        }
                    };
                }
            }()),
            detach:function () {}
        };
        window.ln = ln;
    }(document, window));


</script>
</body>
</html>